#include "./image.h"
#include "graphics/graphics.h"

using namespace MiniUI;
using namespace MiniUI::Type;

const char* TypeObject<Image>::s_szTypeName = "Image";

Image::Image()
: UIObject(GetTypeName())
, m_pBitmap(nullptr)
{
}

Image::~Image()
{
    if (m_pBitmap)
        m_pBitmap->Release();
}

bool Image::RenderTo(Graphics& graphics, const Type::MiniRect& rcRender, const uint8 blendValue)
{
    if (!m_pBitmap) return false;

    graphics.Save();
    //graphics.SetAlpha(((uint16)m_blendValue * (1 + blendValue)) >> 8);
    //UIObject::ShapeClip(graphics);
    MiniRect rcImage(0, 0, m_size.cx, m_size.cy);
    graphics.DrawBitmap(m_pBitmap, nullptr, rcImage);
    graphics.Restore();
    return true;
}

bool Image::SetValue(const char* szImagePath)
{
    m_strImagePath = szImagePath;
	return LoadBitmap(szImagePath);
}

const char* Image::GetValue()
{
    return m_strImagePath.c_str();
}

void Image::SetBitmap(Bitmap* pBitmap)
{
    if (!pBitmap || m_pBitmap == pBitmap)
        return;

    if (m_pBitmap)
        m_pBitmap->Release();

    m_pBitmap = pBitmap;
    m_pBitmap->AddRef();
}

Bitmap* Image::GetBitmap()
{
    return m_pBitmap;
}

bool Image::LoadBitmap(const char* szImagePath)
{
    Decoder decoder(szImagePath);
    decoder.ReadImageInfo();

    DecodeFormat* deco = decoder.GetDecodeFormat();
    if (deco->width > 0 && deco->height > 0)
    {
        m_pBitmap = Bitmap::CreateInstance();
        MiniSize szBitmap(deco->width, deco->height);
		m_pBitmap->Rebuild(szBitmap);
		deco->pOutBuffer = (byte*)m_pBitmap->GetBytes();
		deco->nOutWidthBytes = m_pBitmap->GetWidthBytes();

		if (decoder.ReadImageFrame())
        {
            SetSize(szBitmap);
            //pre multiply color with alpha
            for (int y = szBitmap.cy; y > 0; y--)
            {
                MiniARGB* pLine = (MiniARGB*)m_pBitmap->GetBytes() + szBitmap.cx * (y - 1);
                for (int x = szBitmap.cx; x > 0; x--)
                {
                    pLine->red   = ((pLine->alpha + 1) * pLine->red) >> 8;
                    pLine->green = ((pLine->alpha + 1) * pLine->green) >> 8;
                    pLine->blue  = ((pLine->alpha + 1) * pLine->blue) >> 8;
                    pLine++;
                }
            }
        }
        else
        {
            return false;
        }
    }

    return false;
}